package com.httam.taxiSmart;

import java.text.DecimalFormat;
import java.util.ArrayList;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Color;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.provider.Settings;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.model.PolylineOptions;

public class GPSCostActivity extends FragmentActivity implements
		OnItemSelectedListener, LocationListener {

	// The minimum distance to change updates in meters
	private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 1; // meters

	// The minimum time between updates in milliseconds
	private static final long MIN_TIME_BW_UPDATES = 3000; // in miliseconds

	// Handles UI widgets
	private Spinner spnHangTaxi;
	private Spinner spnLoaiXe;
	private TextView txtKm;
	private TextView txtGiacuoc;
	private Button btnStartGPS;

	// Google map object
	private GoogleMap mMap;

	long distance = 0;

	int count = 0;

	// Location manager object
	protected LocationManager locationManager;
	private Location myLocation;
	double myLatitude; // latitude
	double myLongitude; // longitude

	// Flag for GPS status
	boolean isGPSEnabled = false;

	boolean start = false;
	boolean stop = false;
	MarkerOptions markerOptions;
	ArrayList<LatLng> listLatLng = null;
	PolylineOptions lineOptions = null;

	// Declare variable SQLite
	SQLiteDatabase sqlitedB;
	String HangTaxi = null;
	ArrayList<String> arrListTaxi = null;
	ArrayList<String> arrListLoaiXe = null;
	LatLng mLatLng;

	// Connection detector class
	com.httam.taxiSmart.Util.ConnectionDetector connState;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_gpscost);

		if (isGooglePlayService()) {

			setUpMapIfNeeded();
		}

		txtKm = (TextView) findViewById(R.id.lblKm);
		txtGiacuoc = (TextView) findViewById(R.id.lblGiaCuoc);

		spnHangTaxi = (Spinner) findViewById(R.id.spnHangTaxi);
		spnLoaiXe = (Spinner) findViewById(R.id.spnLoaiXe);

		// Connect to SQLite database
		sqlitedB = openOrCreateDatabase(MainActivity.pathSQLite, MODE_PRIVATE,
				null);
		Cursor curSor = sqlitedB.query("HangTaxi", null, null, null, null,
				null, null);
		arrListTaxi = new ArrayList<String>();
		curSor.moveToFirst();
		while (!curSor.isAfterLast()) {
			String data = curSor.getString(1);
			arrListTaxi.add(data);
			curSor.moveToNext();
		}

		curSor.close();

		ArrayAdapter<String> adapterTaxi = new ArrayAdapter<String>(this,
				android.R.layout.simple_spinner_item, arrListTaxi);
		adapterTaxi
				.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		spnHangTaxi.setAdapter(adapterTaxi);
		spnHangTaxi.setOnItemSelectedListener(this);

		btnStartGPS = (Button) findViewById(R.id.btnStartGPS);
		btnStartGPS.setText("Start");
		btnStartGPS.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				if (start == false) {
					start = true;
					btnStartGPS.setText("Stop");
					btnStartGPS.setTextColor(Color.RED);
				} else {
					start = false;
					btnStartGPS.setText("Start");
					btnStartGPS.setTextColor(Color.WHITE);

					Handler handler = new Handler();
					handler.postDelayed(new Runnable() {

						@Override
						public void run() {
							showDialogCompare();
						}
					}, 2000);
				}
			}
		});
	}

	private void showDialogCompare() {
		DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int which) {
				switch (which) {
				case DialogInterface.BUTTON_POSITIVE:
					// start the compare cost taxi activity here
					Intent intent = new Intent(GPSCostActivity.this,
							CompareCostActivity.class);
					// Create Bundle to containing object
					Bundle bundle = new Bundle();
					String data = txtGiacuoc.getText().toString()
							+ "    Distance: " + txtKm.getText().toString();
					// Bind data to bundle
					bundle.putString("FEE", data);
					// attach the bundle object to intent
					intent.putExtras(bundle);

					startActivity(intent);
					break;
				case DialogInterface.BUTTON_NEGATIVE:
					dialog.dismiss();
					break;
				}
			}
		};

		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setMessage("Do you want compare taxi cost?")
				.setIcon(R.drawable.ic_launcher).setTitle(R.string.app_name)
				.setPositiveButton("Yes", dialogClickListener)
				.setNegativeButton("No", dialogClickListener).show();
	}

	private boolean isGooglePlayService() {

		// Check Google play services is available
		int resultCode = GooglePlayServicesUtil
				.isGooglePlayServicesAvailable(this);

		// If Google play services is available
		if (resultCode == ConnectionResult.SUCCESS) {
			// Continue
			return true;

			// Google Play Services was not available for some reason
		} else {
			// Display an error dialog
			Dialog dialog = GooglePlayServicesUtil.getErrorDialog(resultCode,
					this, 0);
			if (dialog != null) {
				ErrorDialogFragment errorFragment = new ErrorDialogFragment();
				errorFragment.setDialog(dialog);
				errorFragment.show(getSupportFragmentManager(),
						"GooglePlayServices");
			}
			return false;
		}
	}

	private void setUpMapIfNeeded() {
		if (mMap == null) {

			SupportMapFragment mf = (SupportMapFragment) getSupportFragmentManager()
					.findFragmentById(R.id.gps_map);
			mMap = mf.getMap();

			if (mMap != null) {

				setUpMap();
			}
		}
	}

	private void setUpMap() {
		locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

		// Enable MyLocation Layer of Google Map
		mMap.setMyLocationEnabled(true);

		try {
			// Getting GPS status
			isGPSEnabled = locationManager
					.isProviderEnabled(LocationManager.GPS_PROVIDER);
			if (!isGPSEnabled) {
				showSettingAlert();

			} else {
				listLatLng = new ArrayList<LatLng>();
				lineOptions = new PolylineOptions().width(9).color(Color.GRAY);

				// Get best provider
				Criteria criteria = new Criteria();
				criteria.setAccuracy(Criteria.ACCURACY_FINE);
				criteria.setBearingRequired(true);
				criteria.setBearingAccuracy(Criteria.ACCURACY_HIGH);
				criteria.setHorizontalAccuracy(Criteria.ACCURACY_HIGH);
				String provider = locationManager.getBestProvider(criteria,
						true);

				if (provider == null) {
					onProviderDisabled(provider);
				}

				// Get current location
				myLocation = locationManager.getLastKnownLocation(provider);
				if (myLocation != null) {
					onLocationChanged(myLocation);
				}
				locationManager.requestLocationUpdates(provider,
						MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES,
						this);
				myLatitude = myLocation.getLatitude();
				myLongitude = myLocation.getLongitude();
				mLatLng = new LatLng(myLatitude, myLongitude);

			}
		} catch (Exception e) {
			// Log.e("setUp Google maps", e.getMessage());
			e.printStackTrace();
		}

	}

	@Override
	public void onItemSelected(AdapterView<?> parent, View view, int position,
			long id) {
		String tenHangTaxi = spnHangTaxi.getSelectedItem().toString();
		addItemsLoaiXe(tenHangTaxi);
	}

	@Override
	public void onNothingSelected(AdapterView<?> parent) {
	}

	private void addItemsLoaiXe(String tenHang) {
		spnLoaiXe = (Spinner) findViewById(R.id.spnLoaiXe);

		sqlitedB = openOrCreateDatabase(MainActivity.pathSQLite, MODE_PRIVATE,
				null);
		Cursor curSor = null;
		String sql = "select LoaiXe.TenLoai from LoaiXe, HangTaxi where HangTaxi.ID_HangTaxi = LoaiXe.ID_HangTaxi and HangTaxi.TenHang = '"
				+ tenHang + "'";
		curSor = sqlitedB.rawQuery(sql, null);
		arrListLoaiXe = new ArrayList<String>();
		curSor.moveToFirst();
		while (!curSor.isAfterLast()) {
			String data = curSor.getString(0);
			arrListLoaiXe.add(data);
			curSor.moveToNext();
		}

		curSor.close();

		ArrayAdapter<String> adapterLx = new ArrayAdapter<String>(this,
				android.R.layout.simple_spinner_item, arrListLoaiXe);
		adapterLx
				.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		spnLoaiXe.setAdapter(adapterLx);
	}

	@Override
	public void onLocationChanged(Location location) {

		double latitude = location.getLatitude();

		// Get longitude of the current location
		double longitude = location.getLongitude();

		// Create a LatLng object for the current location
		LatLng latLng = new LatLng(latitude, longitude);

		// Show the current location in Google Map
		mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));

		// Zoom in the Google Map
		mMap.animateCamera(CameraUpdateFactory.zoomTo(16));

		mMap.addMarker(new MarkerOptions().position(
				new LatLng(latitude, longitude)).title("My Location"));

		Toast.makeText(GPSCostActivity.this, "Location has changed",
				Toast.LENGTH_LONG).show();

		if (start) {

			Long result = distance2point(myLatitude, myLongitude, latitude,
					longitude);

			Double giacuoc = mTinhGiaCuoc(result * 0.001);
			DecimalFormat formatGiaCuoc = new DecimalFormat("#.##");
			String giaStr = formatGiaCuoc.format(giacuoc);
			Double finalGia = Double.parseDouble(giaStr);

			if (result <= 1000) {
				txtKm.setText(result.toString() + " m");

			} else {
				double convertKm = result * 0.001;
				DecimalFormat decimalFormat = new DecimalFormat("#.##");
				String distanceStr = decimalFormat.format(convertKm);
				Double resultStrt = Double.parseDouble(distanceStr);
				txtKm.setText(resultStrt.toString() + " Km");
			}

			txtGiacuoc.setText(finalGia.toString() + " VNĐ");
		}
		myLatitude = latitude;
		myLongitude = longitude;

	}

	@Override
	public void onStatusChanged(String provider, int status, Bundle extras) {
		Toast.makeText(GPSCostActivity.this, "Provider status changed",
				Toast.LENGTH_LONG).show();
	}

	@Override
	public void onProviderEnabled(String provider) {
		Toast.makeText(GPSCostActivity.this,
				"Provider enabled by the user. GPS turned on",
				Toast.LENGTH_LONG).show();
	}

	@Override
	public void onProviderDisabled(String provider) {
		Toast.makeText(GPSCostActivity.this,
				"Provider disabled by the user. GPS turned off",
				Toast.LENGTH_LONG).show();
	}

	@Override
	protected void onActivityResult(int arg0, int arg1, Intent arg2) {

		super.onActivityResult(arg0, arg1, arg2);
	}

	@Override
	protected void onPause() {

		super.onPause();
		locationManager.removeUpdates(this);
	}

	@Override
	protected void onResume() {

		super.onResume();
		locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
				MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
	}

	@Override
	protected void onStart() {

		super.onStart();
	}

	@Override
	protected void onStop() {

		super.onStop();
	}

	/**
	 * Calculate distance between location
	 */
	private long distance2point(double lat1, double lng1, double lat2,
			double lng2) {

		double dLat = Math.toRadians(lat2 - lat1);
		double dLng = Math.toRadians(lng2 - lng1);
		double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
				+ Math.cos(Math.toRadians(lat1))
				* Math.cos(Math.toRadians(lat2)) * Math.sin(dLng / 2)
				* Math.sin(dLng / 2);
		double c = 2 * Math.asin(Math.sqrt(a));
		distance += Math.round(6371000 * c);

		return distance;
	}

	/**
	 * Show alert setting
	 */
	private void showSettingAlert() {
		AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);

		// Setting Dialog title
		alertDialog.setTitle("GPS is settings");

		// Setting Dialog Message
		alertDialog
				.setMessage("GPS is not enabled. Do you want to go to setting menu");

		// On pressing Setting button
		alertDialog.setPositiveButton("Settings",
				new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						Intent intent = new Intent(
								Settings.ACTION_LOCATION_SOURCE_SETTINGS);
						GPSCostActivity.this.startActivity(intent);
					}
				});

		// on pressing cancel button
		alertDialog.setNegativeButton("Cancel",
				new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						dialog.cancel();
					}
				});

		// Showing Alert Message
		alertDialog.show();
	}

	/** Method calcute gia cuoc taxi by gps **/
	private double mTinhGiaCuoc(double distance) {
		double giacuoc = getGiaMoCua();
		distance = distance - 1;
		if (distance > 0 && distance <= 30) {
			giacuoc += distance * getGiaPhamVi30Km();
		}
		if (distance > 30) {
			giacuoc += 30 * getGiaPhamVi30Km() + (distance - 30)
					* getGiaTren30Km();
		}
		return giacuoc;

	}

	private double getGiaMoCua() {
		String LoaiXe = spnLoaiXe.getSelectedItem().toString();
		String Hangxe = spnHangTaxi.getSelectedItem().toString();
		String sql = "select GiaCuoc.GiaMoCua from LoaiXe, GiaCuoc, HangTaxi where LoaiXe.ID_HangTaxi = HangTaxi.ID_HangTaxi and LoaiXe.ID_Gia = GiaCuoc.ID_Gia and LoaiXe.TenLoai = '"
				+ LoaiXe + "' and HangTaxi.TenHang = '" + Hangxe + "'";
		Cursor curSor = sqlitedB.rawQuery(sql, null);
		curSor.moveToFirst();
		double gia = curSor.getDouble(0);

		return gia;

	}

	private double getGiaPhamVi30Km() {
		String LoaiXe = spnLoaiXe.getSelectedItem().toString();
		String Hangxe = spnHangTaxi.getSelectedItem().toString();
		String sql = "select GiaCuoc.GiaPhamVi30Km from LoaiXe, GiaCuoc, HangTaxi where LoaiXe.ID_HangTaxi = HangTaxi.ID_HangTaxi and LoaiXe.ID_Gia = GiaCuoc.ID_Gia and LoaiXe.TenLoai = '"
				+ LoaiXe + "' and HangTaxi.TenHang = '" + Hangxe + "'";
		Cursor c = sqlitedB.rawQuery(sql, null);
		c.moveToFirst();
		double gia = c.getDouble(0);
		return gia;

	}

	private double getGiaTren30Km() {
		String LoaiXe = spnLoaiXe.getSelectedItem().toString();
		String Hangxe = spnHangTaxi.getSelectedItem().toString();
		String sql = "select GiaCuoc.GiaTren30Km from LoaiXe, GiaCuoc, HangTaxi where LoaiXe.ID_HangTaxi = HangTaxi.ID_HangTaxi and LoaiXe.ID_Gia = GiaCuoc.ID_Gia and LoaiXe.TenLoai = '"
				+ LoaiXe + "' and HangTaxi.TenHang = '" + Hangxe + "'";
		Cursor c = sqlitedB.rawQuery(sql, null);
		c.moveToFirst();
		double gia = c.getDouble(0);
		return gia;

	}

	/**
	 * Define a DialogFragment to display the error dialog generated in
	 * showErrorDialog.
	 */
	public static class ErrorDialogFragment extends DialogFragment {

		// Global field to contain the error dialog
		private Dialog mDialog;

		/**
		 * Default constructor. Sets the dialog field to null
		 */
		public ErrorDialogFragment() {
			super();
			mDialog = null;
		}

		/**
		 * Set the dialog to display
		 * 
		 * @param dialog
		 *            An error dialog
		 */
		public void setDialog(Dialog dialog) {
			mDialog = dialog;
		}

		/*
		 * This method must return a Dialog to the DialogFragment.
		 */
		@Override
		public Dialog onCreateDialog(Bundle savedInstanceState) {
			return mDialog;
		}
	}

}
